package com.example.jimuyutabletcontrol.activity;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.CircleOptions;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.example.jimuyutabletcontrol.R;
import com.example.jimuyutabletcontrol.main.HomeScreenActivity;
import com.example.jimuyutabletcontrol.sensor.LocationSensor;
import com.example.jimuyutabletcontrol.utils.Constants;
import com.example.jimuyutabletcontrol.utils.MeasuringDistancePointHelp;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class MappingActivity extends AppCompatActivity implements View.OnClickListener{

    /*
    private Button mappingLocation;
    private Button startMapping;
    private Button stopMapping;
    private Button cancleMappingData;
    */
    
    private static boolean mappingRecord = false;

    private MapView mapView;
    private BaiduMap baiduMap;
    private LocationClient mLocationClient;
    private MappingActivity.MyLocationListener myLocationListener;
    private LocationSensor locationSensor;

    private double updateLongtitude;
    private double updateLatitude;

    private File file;
    private BufferedWriter bufferedWriter;


    private Point[] pentagonVertices;
    private FloatingActionButton fabTools;
    private Button[] buttonsTools;
    private int startPositionX;
    private int startPositionY;
    private int toolsWhichAnimation;
    private int[] enterDelay = {0, 40, 80, 120, 160, 200, 240};
    private int[] exitDelay = {0, 40, 80, 120, 160, 200, 240};
    private Boolean isFabToolsClicked = false;
    private MeasuringDistancePointHelp distancePointHelp;
    private TextView measureDistance;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mappinginterface_activity);
        mapView = findViewById(R.id.bmapViewmapping);
        baiduMap = mapView.getMap();
        measureDistance = findViewById(R.id.measureDistance);
        setLocationRegister();
        setBaseMapConf();
        //setClickListener();
        initResource();
        prepareFloatButton();
        distancePointHelp = new MeasuringDistancePointHelp(this, baiduMap,1);
        distancePointHelp.setOnMeasuringDistanceListener((isALLShow, distance) -> {
            measureDistance.setVisibility(isALLShow ? View.VISIBLE : View.GONE);
            if (isALLShow) {
                measureDistance.setText("测距距离:" + distance + "米");
            }
        });
    }

    private void initResource() {
        locationSensor = new LocationSensor();
        updateLongtitude = 0.0;
        updateLatitude = 0.0;
        File filePath = new File(Constants.FILE_PATH + Constants.MAPPINGFOLDER);
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
    }

    private void setFileResource() {
        file = new File(Constants.FILE_PATH + Constants.MAPPINGFOLDER + Constants.MAPPINGFILE);
        try {
            bufferedWriter = new BufferedWriter(new FileWriter(file));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void setLocationRegister() {
        mLocationClient = new LocationClient(this);
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true); // 打开gps
        option.setCoorType("bd09ll"); // 设置坐标类型
        option.setScanSpan(1000);
        mLocationClient.setLocOption(option);
        myLocationListener = new MappingActivity.MyLocationListener();
        mLocationClient.registerLocationListener(myLocationListener);
    }

    private class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            //mapView 销毁后不在处理新接收的位置
            if (location == null || mapView == null){
                return;
            }
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    // 此处设置开发者获取到的方向信息，顺时针0-360
                    .direction(location.getDirection()).latitude(location.getLatitude())
                    .longitude(location.getLongitude()).build();
            baiduMap.setMyLocationData(locData);
            MapStatus.Builder builder = new MapStatus.Builder();
            builder.zoom(19.0f);
            baiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
            LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
            MapStatusUpdate status = MapStatusUpdateFactory.newLatLng(ll);
            baiduMap.animateMapStatus(status);//动画的方式到中间
            mLocationClient.stop();
            baiduMap.setMyLocationEnabled(false);
        }
    }

    private void setBaseMapConf() {
        baiduMap.clear();
        MapStatus.Builder builder = new MapStatus.Builder();
        builder.zoom(4.0f);
        baiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
    }

    private LatLng gpsToBaidu(LatLng point) {
        CoordinateConverter converter = new CoordinateConverter();
        converter.from(CoordinateConverter.CoordType.GPS);
        converter.coord(point);
        LatLng changePoint = converter.convert();
        return changePoint;
    }

    private void toastMsg(final String msg) {
        runOnUiThread(()->Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onClick(View view) {
        boolean isToolsSubClicked = false;
        switch (view.getId()) {
            case R.id.fabmappingtool:
                isToolsSubClicked = true;
                isFabToolsClicked = true;
                if (toolsWhichAnimation == 0) {
                    /**
                     * Getting the center point of floating action button
                     *  to set start point of buttons
                     */
                    startPositionX = 2600;
                    startPositionY = 0;
                    for (Button button : buttonsTools) {
                        button.setX(startPositionX);
                        button.setY(startPositionY);
                        button.setVisibility(View.VISIBLE);
                    }
                    for (int i = 0; i < buttonsTools.length; i++) {
                        playEnterAnimation(buttonsTools[i], i);
                    }
                    toolsWhichAnimation = 1;
                } else {
                    for (int i = 0; i < buttonsTools.length; i++) {
                        playExitAnimation(buttonsTools[i], i);
                    }
                    toolsWhichAnimation = 0;
                    isFabToolsClicked = false;
                }
                break;
        }
        if (isFabToolsClicked && !isToolsSubClicked) {
            switch ((int) view.getTag()) {
                case 0:
                    baiduMap.setMyLocationEnabled(true);
                    mLocationClient.start();
                    break;
                case 1:
                    if (file == null) {
                        buttonsTools[1].setEnabled(false);
                        buttonsTools[1].setBackgroundResource(R.drawable.disable_circular_background);
                        buttonsTools[3].setEnabled(false);
                        buttonsTools[3].setBackgroundResource(R.drawable.disable_circular_background);
                        setFileResource();
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                if(!mappingRecord) {
                                    locationSensor.startLocation();
                                    mappingRecord = true;
                                }
                                while (mappingRecord) {
                                    try {
                                        Thread.sleep(5000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                    double[] values = locationSensor.getValue();
                                    System.out.println("longtitude: " + values[0]);
                                    System.out.println("lantitude: " + values[1]);
                                    if (updateLatitude != values[1] || updateLongtitude != values[0]) {
                                        baiduMap.addOverlay(new CircleOptions().center(
                                                gpsToBaidu(new LatLng(values[1], values[0])))
                                                .fillColor(0xffff0000).radius(2));
                                        try {
                                            bufferedWriter.write(values[0] + " " + values[1] + "\n");
                                            bufferedWriter.flush();
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                        updateLongtitude = values[0];
                                        updateLatitude = values[1];
                                    }
                                }
                                try {
                                    bufferedWriter.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                                if (MappingActivity.this != null) {
                                    runOnUiThread(()->{
                                        buttonsTools[1].setEnabled(true);
                                        buttonsTools[1].setBackgroundResource(R.drawable.circular_background);
                                        buttonsTools[3].setEnabled(true);
                                        buttonsTools[3].setBackgroundResource(R.drawable.circular_background);
                                        buttonsTools[2].setEnabled(true);
                                        buttonsTools[2].setBackgroundResource(R.drawable.circular_background);
                                    });
                                }
                            }
                        }).start();
                    } else {
                        toastMsg("请删除上次测绘任务，再开始新的测绘任务");
                    }
                    break;
                case 2:
                    if (mappingRecord) {
                        mappingRecord = false;
                        locationSensor.stopLocation();
                        buttonsTools[2].setEnabled(false);
                        buttonsTools[2].setBackgroundResource(R.drawable.disable_circular_background);
                    } else {
                        toastMsg("无测绘任务需要结束");
                    }
                    break;
                case 3:
                    if (file != null && file.exists()) {
                        file.delete();
                        baiduMap.clear();
                        file = null;
                    } else {
                        toastMsg("无测绘任务需要删除");
                    }
                    break;
            }
        }
    }

    private void prepareFloatButton() {
        startPositionX = 0;
        startPositionY = 0;
        toolsWhichAnimation = 0;
        fabTools = (FloatingActionButton) findViewById(R.id.fabmappingtool);
        fabTools.setOnClickListener(this);
        pentagonVertices = new Point[10];
        pentagonVertices[0] = new Point(10, 100);
        pentagonVertices[1] = new Point(10, 280);
        pentagonVertices[2] = new Point(10, 460);
        pentagonVertices[3] = new Point(10, 640);
        pentagonVertices[4] = new Point(10, 820);
        pentagonVertices[5] = new Point(10, 1000);
        pentagonVertices[6] = new Point(10, 1180);
        String[] contentTools = {"实时定位","开始测绘","结束测绘","删除测绘"};
        buttonsTools = calculatePentagonVertices(4, contentTools);
    }

    private Button[] calculatePentagonVertices(int number, String[] content) {

        Button[] buttons = new Button[number];


        for (int i = 0; i < buttons.length; i++) {
            //Adding button at (0,0) coordinates and setting their visibility to zero
            buttons[i] = new Button(MappingActivity.this);
            buttons[i].setLayoutParams(new RelativeLayout.LayoutParams(100, 100));
            buttons[i].setX(0);
            buttons[i].setY(0);
            buttons[i].setTag(i);
            buttons[i].setOnClickListener(this);
            buttons[i].setVisibility(View.INVISIBLE);
            buttons[i].setBackgroundResource(R.drawable.circular_background);
            buttons[i].setTextColor(Color.DKGRAY);
            buttons[i].setText(content[i]);
            buttons[i].setTextSize(14);
            /**
             * Adding those buttons in acitvities layout
             */
            ((LinearLayout) findViewById(R.id.mapping_main)).addView(buttons[i]);
        }

        return buttons;
    }

    private void playEnterAnimation(final Button button, int position) {

        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(startPositionX,
                pentagonVertices[position].x);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(startPositionY,
                pentagonVertices[position].y);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will increase the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(6, 170);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(enterDelay[position]);
        buttonAnimator.start();
    }

    private void playExitAnimation(final Button button, int position) {

        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(pentagonVertices[position].x,
                startPositionX);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(pentagonVertices[position].y,
                startPositionY);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will decrease the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(170, 6);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(exitDelay[position]);
        buttonAnimator.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != distancePointHelp){
            distancePointHelp.onDestroy();
            distancePointHelp = null;
        }
        locationSensor.stopLocation();
        if (mLocationClient != null) {
            mLocationClient.unRegisterLocationListener(myLocationListener);
            mLocationClient.stop();
            mLocationClient = null;
        }
        if (baiduMap != null) {
            baiduMap = null;
        }
        mapView.onDestroy();
    }

}
